<?php
namespace app\houtai\controller\system;
use app\houtai\controller\BaseController;
use think\db\Expression;
use Exception;

class ServerController extends BaseController {
  private $GO_SERVER_URL = '';
  // 初始化
  protected function _initialize() {
    parent::_initialize();
    $this->GO_SERVER_URL = config('GO_SERVER');
  }
  /**
   *  @brief  : 系统管理-GO游戏开服
   *  @return : page
   *  @details: RYPlatformDB.[dbo].[SigninConfig]
   */
  public function indexAction() {
    $CHANNELS   = $this->GetAdminChannel();
    $GAME_KIND  = GetGameKind();
    $GO_SERVER_TYPE   = config('GO_SERVER_TYPE');
    $GO_SERVER_STATUS = config('GO_SERVER_STATUS');
    $conds = ['Nullity' => 0];  // 没删除的
    $order = [];
    ////////////////////////////////////////////////////////////////////////////
    $channel = $this->request->param('channel/d', -1);
    if ($channel > 0 && array_key_exists($channel, $CHANNELS)) {
      $conds['Channel'][] = ['IN', array_keys($CHANNELS)];
      $conds['Channel'][] = ['EQ', $channel];
    } else {
      $conds['Channel'] = ['IN', array_keys($CHANNELS)];
    }
    ///////////////////////////////////
    $kind = $this->request->param('kind/d', -1);
    if ($kind > 0 && array_key_exists($kind, $GAME_KIND)) {
      $conds['KindID'] = $kind;
    }
    ///////////////////////////////////
    $type = $this->request->param('type/d', -1);
    if ($type > 0 && array_key_exists($type, $GO_SERVER_TYPE)) {
      $conds['Type'] = $type;
    }
    ///////////////////////////////////
    $status = $this->request->param('status/d', -1);
    if ($status >= 0 && array_key_exists($status, $GO_SERVER_STATUS)) {
      $conds['Status'] = $status;
    }
    ////////////////////////////////////////////////////////////////////////////
    $orderMap = [
      'A' => 'ID',
      'B' => 'Channel',
      'C' => 'KindID',
      'D' => 'Title',
      'E' => 'Type',
      'F' => 'Status',
      'G' => 'CreateTime',
      'H' => 'UpdateTime',
      'I' => 'RunTime',
    ];
    
    $this->orderField = array_key_exists($this->orderField, $orderMap) ? $this->orderField : 'I';
    $order[$orderMap[$this->orderField]] = $this->orderDirection;
    ////////////////////////////////////////////////////////////////////////////
    $list = table('GO_GameServerInfo', 'rydb.accounts')->field([
      'ID', 'Channel', 'KindID', 'Title', 'Type', 'Status',
      'CreateTime', 'UpdateTime',
      '(CASE Status WHEN 2 THEN DATEDIFF(hour, SStartTime, GETDATE()) ELSE 0 END)' => 'RunTime',
    ])->where($conds)->order($order)->paginate();
    return $this->fetch('', [
      'CHANNELS'          => $CHANNELS,
      'GAME_KIND'         => $GAME_KIND,
      'GO_SERVER_TYPE'    => $GO_SERVER_TYPE,
      'GO_SERVER_STATUS'  => $GO_SERVER_STATUS,
      'channel'   => $channel,
      'kind'      => $kind,
      'type'      => $type,
      'status'    => $status,
      'list'      => $list,
    ]);
  }
  /**
   *  @brief  : GO游戏开服详情
   *  @return : page|JSON
   *  @details:
   */
  public function detailAction() {
    $id = $this->request->param('id/d', -1);
    $CHANNELS   = $this->GetAdminChannel();
    $GAME_KIND  = GetGameKind();
    $GO_SERVER_TYPE   = config('GO_SERVER_TYPE');
    $GO_SERVER_STATUS = config('GO_SERVER_STATUS');
    if ($this->request->isGet()) {  // 查询/新建 页面
      $data = [];
      if ($id > 0) {
        $data = table('GO_GameServerInfo', 'rydb.accounts')->where('ID', $id)->find();
        if (empty($data)) {
          abort(100, '业务参数无效');
          return;
        }
      }
      return $this->fetch('', [
        'data'              => $data,
        'CHANNELS'          => $CHANNELS,
        'GAME_KIND'         => $GAME_KIND,
        'GO_SERVER_TYPE'    => $GO_SERVER_TYPE,
        'GO_SERVER_STATUS'  => $GO_SERVER_STATUS,
      ]);
    }
    
    if ($this->request->isPost()) { // 保存/新建 请求
      $Channel = $this->request->param('Channel/d', -1);
      if (!array_key_exists($Channel, $CHANNELS)) {
        return result([], 100, "渠道[{$Channel}]未定义");
      }
      
      $Type = $this->request->param('Type/d', -1);
      if (!array_key_exists($Type, $GO_SERVER_TYPE)) {
        return result([], 101, "类型[{$Type}]未定义");
      }
      
      $KindID = $this->request->param('KindID/d', -1);
      if (!array_key_exists($KindID, $GAME_KIND)) {
        return result([], 102, "游戏[{$KindID}]未定义");
      }
      
      $Title = $this->request->param('Title/s', '', 'trim');
      if (empty($Title)) {
        return result([], 103, "服务名称不能为空");
      }
      
      $CustomJSON = $this->request->param('CustomJSON/s', '', 'trim');  // 自定义JSON
      if (!empty($CustomJSON)) {  // 要么不填, 填了就验证JSON有效性
        $data = json_decode($CustomJSON, true);
        $code = json_last_error();
        $erro = '';
        switch ($code) {
          case JSON_ERROR_NONE:           $erro = 'JSON_ERROR_NONE';            break;  // 0
          case JSON_ERROR_DEPTH:          $erro = 'JSON_ERROR_DEPTH';           break; // 1
          case JSON_ERROR_STATE_MISMATCH: $erro = 'JSON_ERROR_STATE_MISMATCH';  break;  // 2
          case JSON_ERROR_CTRL_CHAR:      $erro = 'JSON_ERROR_CTRL_CHAR';       break; // 3
          case JSON_ERROR_SYNTAX:         $erro = 'JSON_ERROR_SYNTAX';          break;    // 4
          case JSON_ERROR_UTF8:           $erro = 'JSON_ERROR_UTF8';            break;    // 5
          default: $erro = ''; break;
        }
        if ($erro != '' && $erro != 'JSON_ERROR_NONE') {
          return result([], 104, "附加JSON错误[{$erro}]");
        }
        $CustomJSON = json_encode($data, JSON_FORCE_OBJECT|JSON_UNESCAPED_UNICODE);
      }
      
      if ($id > 0) {
        $eax = table('GO_GameServerInfo', 'rydb.accounts')->where('ID', $id)->update([
          'Channel'     => $Channel,
          'KindID'      => $KindID,
          'Title'       => $Title,
          'Type'        => $Type,
          'CustomJSON'  => $CustomJSON,
          'UpdateTime'  => new Expression('GETDATE()'),
        ]);
        $action = 'update';
      } else {
        $id = table('GO_GameServerInfo', 'rydb.accounts')->insertGetId([
          'Channel'     => $Channel,
          'KindID'      => $KindID,
          'Title'       => $Title,
          'Type'        => $Type,
          'CustomJSON'  => $CustomJSON,
          'UpdateTime'  => new Expression('GETDATE()'),
        ]);
        $action = 'create';
      }

      // 通知GO服务器
      try {
        $srv = table('GO_GameServerInfo', 'rydb.accounts')->where('ID', $id)->find();
        unset($srv['ROW_NUMBER'], $srv['SStartTime'], $srv['Status'], $srv['Nullity']);
        $conf = json_decode($srv['CustomJSON'], true);
        unset($srv['CustomJSON']);
        $conf['game_config'] = $srv;
        $data = json_encode($conf, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
        $data = ['data' => $data];
        trace($data);
        $retn = CallGameSrv("index.html?s=server/config/{$action}", $data, $this->GO_SERVER_URL); // 创建或更新服务, 返回'SUCCESS'/'FAILURE'
      } catch (Exception $e) {
        $error = $e->getMessage();
        $errno = $e->getCode();
        return result([], $errno, "更新成功, 通知GO服务器失败[{$error}]");
      }
      
      return result([], 0);
    }
  }
  /**
   *  @brief  : 删除GO游戏服务
   *  @return : 
   *  @details:
   */
  public function deleteAction() {
    
    if (!$this->request->isPost()) {
      return result([], 100, '非法请求');
    }
    $id = $this->request->param('id/d', -1);
    if ($id <= 0) {
      return result([], 101, '业务参数无效');
    }
    $srv = table('GO_GameServerInfo', 'rydb.accounts')->where('ID', $id)->find();
    if ($id <= 0) {
      return result([], 102, "服务不存在ID={$id}");
    }
    // 标记删除
    table('GO_GameServerInfo', 'rydb.accounts')->where('ID', $id)->setField('Nullity', 1);
/*
    // 通知GO服务器
    try {
      unset($srv['ROW_NUMBER'], $srv['SStartTime'], $srv['Status'], $srv['Nullity']);
      $srv['CustomJSON'] = json_decode($srv['CustomJSON'], true);
      $data = json_encode($srv, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
      $data = ['data' => $data];
      trace($data);
      $retn = CallGameSrv('index.html?s=server/config/delete', $data, $this->GO_SERVER_URL);  // 删除服务, 返回'SUCCESS'/'FAILURE'
    } catch (Exception $e) {
      $error = $e->getMessage();
      $errno = $e->getCode();
      return result([], $errno, "更新成功, 通知GO服务器失败[{$error}]");
    }
*/
    return result([], 0);
  }
  /**
   *  @brief  : 切换GO游戏服务状态
   *  @return : 
   *  @details: Status 0=未运行(启动); 1=开启中(启动); 2=运行中(关闭); 3=关闭中(关闭);
   */
  public function switchAction() {
    if (!$this->request->isPost()) {
      return result([], 100, '非法请求');
    }
    $id     = $this->request->param('id/d', -1);
    $state  = $this->request->param('state/d', -1);
    if ($id <= 0 || !in_array($state, [0, 1, 2, 3])) {
      return result([], 101, '业务参数无效');
    }
    /////////////////////////////////////////////////
    $srv = table('GO_GameServerInfo', 'rydb.accounts')->where(['ID' => $id, 'Nullity' => 0])->find();
    if ($id <= 0) {
      return result([], 102, "服务不存在ID={$id}");
    }

    // 通知GO服务器
    try {
      unset($srv['ROW_NUMBER'], $srv['SStartTime'], $srv['Nullity']);
      $conf = json_decode($srv['CustomJSON'], true);
      unset($srv['CustomJSON']);
      $conf['game_config'] = $srv;
      $data = json_encode($conf, JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE);
      $data = ['data' => $data];
      trace($data);
      if (in_array($srv['Status'], [0, 1])) {
        $action = 'start';
      } else if (in_array($srv['Status'], [2, 3])) {
        $action = 'close';
      }
      $retn = CallGameSrv("index.html?s=server/config/{$action}", $data, $this->GO_SERVER_URL); // 切换GO服务状态, 返回'SUCCESS'/'FAILURE'
      if (false) {
        /*
        table('GO_GameServerInfo', 'rydb.accounts')->where('ID', $id)->update([
          
        ]);
        */
      }
    } catch (Exception $e) {
      $error = $e->getMessage();
      $errno = $e->getCode();
      return result([], $errno, "更新成功, 通知GO服务器失败[{$error}]");
    }

    return result([], 10);
  }
}
